/*
 * Created by 岱青海蓝信息系统(北京)有限公司 on 17-5-15 上午11:55
 * Copyright (c) 2017. All rights reserved.
 */

package com.example.dqhl.recycleviewdemo.view;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;

/**
 * Created by dqhl on 17/5/15.
 */
public class ObservableScrollView extends ScrollView {

    public interface OnScrollListener {

        int SCROLL_STATE_IDLE = 0;

        /**
         * 用户滚动使用触摸，他们的手指仍然在屏幕上
         */
        int SCROLL_STATE_TOUCH_SCROLL = 1;

        /**
         * 用户以前使用触摸滚动，并进行了投掷。动画现在是滑行到停止
         */
        int SCROLL_STATE_FLING = 2;

        void onScrollStateChanged(ObservableScrollView view,int scrollState);

        void onScroll(ObservableScrollView view,boolean isTouchScroll,int l,int t, int oldl, int oldt);
    }

    private static final boolean DEBUG = false;

    private static final int CHECK_SCROLL_STOP_DELAY_MILLIS = 80;
    private static final int MSG_SCROLL = 1;

    private boolean mIsTouched = false;
    private int mScrollState = OnScrollListener.SCROLL_STATE_FLING;

    private OnScrollListener mOnScrollListener;

    private final Handler mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {

        private int mLastY = Integer.MIN_VALUE;

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == MSG_SCROLL) {
                final int scrollY = getScrollY();
                Log.e("GG","handleMessage, lastY = " + mLastY + ", y = " + scrollY);
                if (!mIsTouched && mLastY == scrollY) {
                    mLastY = Integer.MIN_VALUE;
                    setScrollState(OnScrollListener.SCROLL_STATE_IDLE);
                } else {
                    mLastY = scrollY;
                    restartCheckStopTiming();
                }
                return true;
            }
            return false;
        }
    });
    private void restartCheckStopTiming() {
        mHandler.removeMessages(MSG_SCROLL);
        mHandler.sendEmptyMessageDelayed(MSG_SCROLL, CHECK_SCROLL_STOP_DELAY_MILLIS);
    }

    public ObservableScrollView(Context context) {
        super(context);
    }

    public ObservableScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setOnScrollListener(OnScrollListener onScrollListener) {
        mOnScrollListener = onScrollListener;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        handleDownEvent(ev);
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        handleUpEvent(ev);
        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
//        Log.e("GG",String.format("onScrollChanged, isTouched = %s, l: %d --> %d, t: %d --> %d", mIsTouched, oldl, l, oldt, t));
        if (mIsTouched) {
            setScrollState(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
        } else {
            setScrollState(OnScrollListener.SCROLL_STATE_FLING);
            restartCheckStopTiming();
        }
        if (mOnScrollListener != null) {
            mOnScrollListener.onScroll(this, mIsTouched, l, t, oldl, oldt);
        }
    }

    private void handleDownEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.e("GG","handleEvent, action = " + ev.getAction());
                mIsTouched = true;
                break;
        }
    }

    private void handleUpEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                Log.e("GG","handleEvent, action = " + ev.getAction());
                mIsTouched = false;
                restartCheckStopTiming();
                break;
        }
    }

    private void setScrollState(int state) {
        if (mScrollState != state) {
            Log.e("GG",String.format("---- onScrollStateChanged, state: %d --> %d", mScrollState, state));
            mScrollState = state;
            if (mOnScrollListener != null) {
                mOnScrollListener.onScrollStateChanged(this, state);
            }
        }
    }

    private void log(String obj) {
        if (DEBUG) {
            Log.d(getClass().getSimpleName(), obj);
        }
    }
}
